package com.jbm.core.common;

import com.jbm.core.client.MainCallback;
import com.jbm.core.iface.IAcross;
import com.jbm.core.iface.ICallGroup;
import com.jbm.core.iface.IP2P;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Random;
import java.util.concurrent.Executors;

/**
 * Created by root on 17-3-22.
 */
public class MainServer
{
	protected static Logger logger = LoggerFactory.getLogger(MainServer.class);
	public static final char Server_type_Server = 0;
	public static final char Server_type_Client = 1;

	public static final MainServer g_server = new MainServer();
//	public static P2PServer g_p2pserver = null;

	protected MainCallback m_maincallback;
	private Integer m_local_id;
	private String m_app_type;

	protected char m_server_type;

	protected int m_localport;

	private IoAcceptor m_acceptor;

	public MainServer()
	{
	}

	public void Init(String config,
	                 String serverhost,
	                 int serverport,
	                 String app_type,
	                 MainCallback callback )
	{
		m_app_type = app_type;

		if ( app_type.equals("app_server"))
		{
			m_server_type = Server_type_Server;

			AutoCall.g_autocall.InitAC(1000,
					"IP2P.Match|keepalive.|1st.|" +
							"IRegister.Register|" +
							"IAccCtrl.GetAccList",
					"com.jbm.core" +
							"|com.jbm.onehome",
					"com.jbm.core.server|" +
							"com.jbm.onehome");

			m_localport = 1920;
			m_maincallback = null;
			m_local_id = AccountCtrl.Account_Server_id;

			AccountCtrl.g_accountctrl.InitAccountqueue(100);

			try
			{
				m_acceptor = new NioSocketAcceptor();
				// 设置过滤器
				m_acceptor.getFilterChain().addLast("logger", new LoggingFilter());
				m_acceptor.getFilterChain().addLast("codec",
						new ProtocolCodecFilter(new OHCodeFactory("UTF-8")));
				m_acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));
				// 设置读取数据的缓冲区大小
				m_acceptor.getSessionConfig().setReadBufferSize(4096);
				// 读写通道10秒内无操作进入空闲状态
				m_acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);

				//Init HeartBeat
/*
			KeepAliveMessageFactory kamf = new JBMKeepAliveMessageFactory(HBType.SERVER);
			KeepAliveFilter kaf = new KeepAliveFilter(kamf, IdleStatus.BOTH_IDLE);
			kaf.setForwardEvent(true);
			kaf.setRequestInterval(10);
			acceptor.getFilterChain().addLast("heart", kaf);
*/

				// 绑定逻辑处理器
				m_acceptor.setHandler(new MainHandler());
				// 绑定端口
				m_acceptor.bind(new InetSocketAddress(m_localport));
				logger.info("服务端启动成功... 端口号为：" + m_localport);
			}catch (Exception e)
			{
				logger.error("服务端启动异常....", e);
				e.printStackTrace();
			}
		}else
		{
			m_server_type = Server_type_Client;

			AutoCall.g_autocall.InitAC(1000,
					"IConnectAgent.PushCA|" +
							"IConnectAgent.OfflineCA|" +
							"IP2P.PushPoint",
					"com.jbm.core" +
							"|com.jbm.onehome",
					"com.jbm.core.client|" +
							"com.jbm.onehome.client");

			Random r = new Random();
			m_localport = (int)(r.nextInt(8000)+2000);

			m_maincallback = callback;
			m_local_id = 0;

			AccountCtrl.g_accountctrl.InitAccountmap();
		}

		AccountCtrl.g_accountctrl.InitCAqueue(200);


		if ( m_server_type == Server_type_Client )
		{
			ConnectAgent ca = new ConnectAgent("app_server",serverhost,serverport,m_localport,MainServer.Server_type_Client,5000);

			AccountCtrl.g_accountctrl.PushPoint(AccountCtrl.Account_Server_id,ca);

			AccountCtrl.g_accountctrl.Connect2Server(AccountCtrl.Account_Server_id,"app_server");
		}
	}

	public int getM_localport()
	{
		return m_localport;
	}

	public void setM_local_id ( Integer local_id )
	{
		m_local_id = local_id;
	}

	public Integer getM_local_id()
	{
		return m_local_id;
	}

	public String getM_app_type()
	{
		return m_app_type;
	}

	public char getM_server_type()
	{
		return m_server_type;
	}

	public MainCallback getM_maincallback()
	{
		return m_maincallback;
	}

	public IAcross SendText (Integer receiver, String app_type, String msg )
	{
		return Remote(receiver, app_type,
				new IP2P(MainServer.g_server.getM_local_id(), msg, true), "PushPoint", true, true);
	}

	public IAcross Remote (Integer to_id, String app_type, IAcross content, String method, boolean hasresp, boolean waitresp )
	{
		return AccountCtrl.g_accountctrl.SendPoint(to_id, app_type, null, method, content, hasresp, waitresp);
	}

	public ICallGroup CreateGroup ( )
	{
		IAcross ia = (IAcross) Remote(AccountCtrl.Account_Server_id,"app_server",new ICallGroup(),"Create",true,true);

		if ( ia.m_code == 200 )
		{
			ICallGroup cg = (ICallGroup)ia;

			Remote(AccountCtrl.Account_Server_id, "app_server", new ICallGroup(cg.m_cg_id, m_local_id), "Start", true, true);

			return cg;
		}else
			return new ICallGroup(ia.m_code,ia.m_info);
	}

	public ICallGroup AddAccount( int cg_id, int account_id )
	{
		return (ICallGroup) Remote(AccountCtrl.Account_Server_id,"app_server",new ICallGroup(cg_id, account_id),"AddAccount",true,true);
	}

	public ICallGroup DropAccount( int cg_id, int account_id )
	{
		return (ICallGroup) Remote(AccountCtrl.Account_Server_id,"app_server",new ICallGroup(cg_id, account_id),"DropAccount",true,true);
	}
}
